library(shiny)
Registered S3 methods overwritten by 'htmltools':
  method               from         
  print.html           tools:rstudio
  print.shiny.tag      tools:rstudio
  print.shiny.tag.list tools:rstudio
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ────────────────────────────────────────────────────── tidyverse 1.3.2 ──✔ ggplot2 3.3.6     ✔ purrr   0.3.4
✔ tibble  3.1.8     ✔ dplyr   1.0.9
✔ tidyr   1.2.0     ✔ stringr 1.4.0
✔ readr   2.1.2     ✔ forcats 0.5.1── Conflicts ───────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
obps_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/LKOH-GMKN-2007-10-08-09_obps.csv")
Rows: 394482 Columns: 12── Column specification ───────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (2): SECCODE, BUYSELL
dbl  (9): NO, TIME, ORDERNO, ACTION, PRICE, VOLUME, TRADENO, TRADEPRICE, OBPLOTNO
date (1): DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# obps_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/LKOH-2007-10-08_obps.csv")
# obps_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/s1_s2_2007_obps.csv")
obps_df <- obps_df %>% 
  mutate(TIME_S = TIME/1000)
obps_df
order_atts_cumsums_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/LKOH-GMKN-2007-10-08-09_order_atts_cumsums.csv")
Rows: 394482 Columns: 32── Column specification ───────────────────────────────────────────────────────────────────────
Delimiter: ","
chr   (2): ATT, SECCODE
dbl  (28): VAL, NO, OBPLOTNO, SHAREBAL, BPROFIT, SPROFIT, OBPMINTPRICE, OBPMAXTPRICE, CBOVO...
dttm  (1): DATETIMEMLLS
date  (1): DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# order_atts_cumsums_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/LKOH-2007-10-08_order_atts_cumsums.csv")
# order_atts_cumsums_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/s1_s2_2007_order_atts_cumsums.csv")
order_atts_cumsums_df
obp_cum_atts_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/LKOH-GMKN-2007-10-08-09_obp_cum_atts.csv")
Rows: 75021 Columns: 6── Column specification ───────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (3): SECCODE, BUYSELLOBP, TRADESNOTRADES
dbl  (2): OBPLOTNO, TRADEVOL
date (1): DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# obp_cum_atts_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/LKOH-2007-10-08_obp_cum_atts.csv")
# obp_cum_atts_df <- read_csv("../order-book-plot-find/cum_errors/resources/for_web_app/s1_s2_2007_obp_cum_atts.csv")
obp_cum_atts_df
order_atts_cumsums_enhanced_df <- left_join(order_atts_cumsums_df, 
                                         obps_df %>% select(-OBPLOTNO, -SECCODE), 
                                         by = c("NO", "DATE")) %>% 
  select(NO, SECCODE, DATETIMEMLLS, PRICE, TRADEPRICE, VOLUME, 
         DATE, TIME_S, OBPLOTNO, ATT, VAL, 
         SHAREBAL, BPROFIT, SPROFIT, OBPMINTPRICE, OBPMAXTPRICE,
         CBOVOLtdcs, CSOVOLtdcs, BOVOLtdcs, SOVOLtdcs, BTVOLtdcs, STVOLtdcs, 
         CBOVOLobpcs, CSOVOLobpcs, BOVOLobpcs, SOVOLobpcs, BTVOLobpcs, STVOLobpcs,
         sobp, bobp, max_sobp_bobp, minus_max_sobp_bobp, stday, btday, max_std_btd,
         minus_max_std_btd)
order_atts_cumsums_enhanced_df
obp_minmax_atts_df <- order_atts_cumsums_enhanced_df %>% 
  select(NO, SECCODE, DATE, OBPLOTNO, ATT,
         DATETIMEMLLS, PRICE, TRADEPRICE) %>% 
  group_by(SECCODE, DATE, OBPLOTNO) %>% 
  summarise(OBPBEGIN = min(DATETIMEMLLS), OBPEND = max(DATETIMEMLLS), 
            OBPBEGINNO = min(NO), OBPENDNO = max(NO),
            OBPMINPRICE = min(PRICE), OBPMAXPRICE = max(PRICE))
`summarise()` has grouped output by 'SECCODE', 'DATE'. You can override using the `.groups` argument.
obp_minmax_atts_df
obp_cum_minmax_atts_df <- left_join(obp_cum_atts_df, 
                                    obp_minmax_atts_df %>% select(SECCODE,
                                                                  DATE,
                                                                  OBPLOTNO,
                                                                  OBPBEGIN,
                                                                  OBPBEGINNO,
                                                                  OBPENDNO,
                                                                  OBPEND,
                                                                  OBPMINPRICE,
                                                                  OBPMAXPRICE),
                                    by = c("SECCODE", "DATE", "OBPLOTNO")) %>% 
  select(SECCODE, DATE, OBPLOTNO, TRADEVOL, BUYSELLOBP,
         OBPBEGIN, OBPEND, OBPBEGINNO, OBPENDNO, OBPMINPRICE, OBPMAXPRICE,
         TRADESNOTRADES) #, BUYSELLYIELD, OBPTDVOLRATIO, MINMAXRATIO)
obp_cum_minmax_atts_df
oas_att_bst <- order_atts_cumsums_enhanced_df %>% 
  select(NO, SECCODE, DATE, OBPLOTNO, ATT, TRADEPRICE) %>% 
  filter(ATT == "BTVOL" | ATT == "STVOL")
oas_att_bst
obp_minmax_tradeprice <- function(seccode, date, obplotno, 
                                  obpbeginno, obpendno, tradesnotrades, minmax) {
  # print(paste(length(seccode),
  #             length(date),
  #             length(obplotno),
  #             length(obpbeginno),
  #             length(obpendno),
  #             length(minmax)))
  # print(paste(seccode, date, obplotno, obpbeginno, obpendno, minmax))
  # seq(length(obplotno))
  if(tradesnotrades == "Y") {
    if (minmax == "min") {
      mint <- min(oas_att_bst %>%
                    filter(SECCODE == seccode & DATE == date & 
                             NO >= obpbeginno & NO <= obpendno) %>% 
                    .$TRADEPRICE %>%
                    cummin())
      # print(mint)
      mint
    } else if (minmax == "max") {
      maxt <- max(oas_att_bst %>%
                    filter(SECCODE == seccode & DATE == date & 
                             NO >= obpbeginno & NO <= obpendno) %>% 
                    .$TRADEPRICE %>%
                    cummax())
      # print(maxt)
      maxt
      
    } else {
      print(paste0("min or max only, not ", minmax))
      stop()
    }
  } else {
    NA
  }
}
vextor_to_obp_minmax_tradeprice <- function(seccode, date, obplotno, 
                                            obpbeginno, obpendno, tradesnotrades, minmax) {
  tibble(seccode, date, obplotno, obpbeginno, obpendno, tradesnotrades,
         minmax = rep(minmax, length(obplotno))) %>% 
    pmap(obp_minmax_tradeprice) %>% 
    unlist()
}
obp_cum_tprice_atts <- obp_cum_minmax_atts_df %>% 
  # sample_n(20) %>% 
  group_by(SECCODE, DATE) %>% 
  summarise(OBPLOTNO = OBPLOTNO,
            OBPMINTRADEPRICE = vextor_to_obp_minmax_tradeprice(SECCODE,
                                                               DATE,
                                                               OBPLOTNO,
                                                               OBPBEGINNO,
                                                               OBPENDNO,
                                                               TRADESNOTRADES,
                                                               "min"),
            OBPMAXTRADEPRICE = vextor_to_obp_minmax_tradeprice(SECCODE,
                                                               DATE,
                                                               OBPLOTNO,
                                                               OBPBEGINNO,
                                                               OBPENDNO,
                                                               TRADESNOTRADES,
                                                               "max"))
`summarise()` has grouped output by 'SECCODE', 'DATE'. You can override using the `.groups` argument.
obp_cum_tprice_atts
obp_cum_minmax_tpminmax_atts_df <- left_join(obp_cum_minmax_atts_df,
                                             obp_cum_tprice_atts,
                                             by = c("SECCODE", "DATE", "OBPLOTNO"))
obp_cum_minmax_tpminmax_atts_df
obp_cum_atts_enh_df <- inner_join(obp_cum_minmax_tpminmax_atts_df,
                                  order_atts_cumsums_enhanced_df %>% select(SECCODE,
                                                                            DATE,
                                                                            OBPLOTNO,
                                                                            BPROFIT,
                                                                            SPROFIT),
                                  by = c("SECCODE", "DATE", "OBPLOTNO")) %>% 
  select(SECCODE, DATE, OBPLOTNO, TRADEVOL, BUYSELLOBP,
         BPROFIT, SPROFIT,
         OBPBEGIN, OBPEND, OBPBEGINNO, OBPENDNO, OBPMINPRICE, OBPMAXPRICE,
         OBPMINTRADEPRICE, OBPMAXTRADEPRICE, TRADESNOTRADES) %>% #, BUYSELLYIELD, OBPTDVOLRATIO, MINMAXRATIO) %>% 
  rename("seccode" = "SECCODE",
         "ddate" = "DATE",
         "obplotno" = "OBPLOTNO",
         "tradevol" = "TRADEVOL",
         "buysellobp" = "BUYSELLOBP",
         "bprofit" = "BPROFIT",
         "sprofit" = "SPROFIT",
         "obpbegin" = "OBPBEGIN",
         "obpend" = "OBPEND",
         "obpbeginno" = "OBPBEGINNO",
         "obpendno" = "OBPENDNO",
         "obpminprice" = "OBPMINPRICE",
         "obpmaxprice" = "OBPMAXPRICE",
         "obpmintradeprice" = "OBPMINTRADEPRICE",
         "obpmaxtradeprice" = "OBPMAXTRADEPRICE",
         "bprofit" = "BPROFIT",
         "sprofit" = "SPROFIT",
         "tradesnotrades" = "TRADESNOTRADES") %>% 
  distinct()
obp_cum_atts_enh_df
td_vol_sum_df <- obp_cum_atts_enh_df %>% 
  group_by(seccode, ddate) %>% 
  summarise(tdvolsum = sum(tradevol))
`summarise()` has grouped output by 'seccode'. You can override using the `.groups` argument.
obp_cum_atts_enh_volarranged_df <- left_join(obp_cum_atts_enh_df,
          td_vol_sum_df,
          by = c("seccode", "ddate")) %>% 
  mutate(obpshareintd = tradevol / tdvolsum) %>% 
  select(-tdvolsum) %>% 
  arrange(seccode, ddate, desc(obpshareintd))

obp_cum_atts_enh_volarranged_df
options(digits.secs = 3)
obp_cum_atts_enh_volarranged_df %>%
  write_csv("../order-book-plot-find/cum_errors/resources/for_web_app/obp_cum_atts_enh_df.csv",
            na = "")
order_atts_cumsums_enh2_df <- order_atts_cumsums_enhanced_df %>% 
  mutate(pcolor = if_else(ATT == "BOVOL", 
                          "aquamarine", 
                          if_else(ATT == "SOVOL",
                                  "coral",
                                  "#004481")),
         pshape = 4L,
         psize = 0.5)
order_atts_cumsums_enh2_df
order_atts_cumsums_enh4_df <- order_atts_cumsums_enh2_df %>% 
  arrange(SECCODE, DATE, NO) %>% 
  rename("nno" = "NO",
         "seccode" = "SECCODE",
         "datetimemlls" = "DATETIMEMLLS",
         "price" = "PRICE",
         "tradeprice" = "TRADEPRICE",
         "volume" = "VOLUME",
         "ddate" = "DATE",
         "ttime_s" = "TIME_S",
         "obplotno" = "OBPLOTNO",
         "att" = "ATT",
         "val" = "VAL",
         "sharebal" = "SHAREBAL") %>% 
  select(-BPROFIT, -SPROFIT, -OBPMINTPRICE, -OBPMAXTPRICE)
# options(digits.secs = 3)
order_atts_cumsums_enh4_df %>%
  write_csv("../order-book-plot-find/cum_errors/resources/for_web_app/order_atts_cumsums_enh4_df.csv",
            na = "")
order_atts_cumsums_enh4_df
order_atts_cumsums_enh4_df %>% 
  filter(obplotno == 48851, att == "STVOL") %>% 
  select(nno, price, att, tradeprice, sobp, bobp)
LS0tDQp0aXRsZTogInByZXBhcmVfYmFsX3Rlc3RpbmdfZGZzIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KDQpgYGB7cn0NCmxpYnJhcnkoc2hpbnkpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmBgYA0KYGBge3J9DQpvYnBzX2RmIDwtIHJlYWRfY3N2KCIuLi9vcmRlci1ib29rLXBsb3QtZmluZC9jdW1fZXJyb3JzL3Jlc291cmNlcy9mb3Jfd2ViX2FwcC9MS09ILUdNS04tMjAwNy0xMC0wOC0wOV9vYnBzLmNzdiIpDQojIG9icHNfZGYgPC0gcmVhZF9jc3YoIi4uL29yZGVyLWJvb2stcGxvdC1maW5kL2N1bV9lcnJvcnMvcmVzb3VyY2VzL2Zvcl93ZWJfYXBwL0xLT0gtMjAwNy0xMC0wOF9vYnBzLmNzdiIpDQojIG9icHNfZGYgPC0gcmVhZF9jc3YoIi4uL29yZGVyLWJvb2stcGxvdC1maW5kL2N1bV9lcnJvcnMvcmVzb3VyY2VzL2Zvcl93ZWJfYXBwL3MxX3MyXzIwMDdfb2Jwcy5jc3YiKQ0Kb2Jwc19kZiA8LSBvYnBzX2RmICU+JSANCiAgbXV0YXRlKFRJTUVfUyA9IFRJTUUvMTAwMCkNCm9icHNfZGYNCmBgYA0KDQoNCmBgYHtyfQ0Kb3JkZXJfYXR0c19jdW1zdW1zX2RmIDwtIHJlYWRfY3N2KCIuLi9vcmRlci1ib29rLXBsb3QtZmluZC9jdW1fZXJyb3JzL3Jlc291cmNlcy9mb3Jfd2ViX2FwcC9MS09ILUdNS04tMjAwNy0xMC0wOC0wOV9vcmRlcl9hdHRzX2N1bXN1bXMuY3N2IikNCiMgb3JkZXJfYXR0c19jdW1zdW1zX2RmIDwtIHJlYWRfY3N2KCIuLi9vcmRlci1ib29rLXBsb3QtZmluZC9jdW1fZXJyb3JzL3Jlc291cmNlcy9mb3Jfd2ViX2FwcC9MS09ILTIwMDctMTAtMDhfb3JkZXJfYXR0c19jdW1zdW1zLmNzdiIpDQojIG9yZGVyX2F0dHNfY3Vtc3Vtc19kZiA8LSByZWFkX2NzdigiLi4vb3JkZXItYm9vay1wbG90LWZpbmQvY3VtX2Vycm9ycy9yZXNvdXJjZXMvZm9yX3dlYl9hcHAvczFfczJfMjAwN19vcmRlcl9hdHRzX2N1bXN1bXMuY3N2IikNCm9yZGVyX2F0dHNfY3Vtc3Vtc19kZg0KYGBgDQoNCmBgYHtyfQ0Kb2JwX2N1bV9hdHRzX2RmIDwtIHJlYWRfY3N2KCIuLi9vcmRlci1ib29rLXBsb3QtZmluZC9jdW1fZXJyb3JzL3Jlc291cmNlcy9mb3Jfd2ViX2FwcC9MS09ILUdNS04tMjAwNy0xMC0wOC0wOV9vYnBfY3VtX2F0dHMuY3N2IikNCiMgb2JwX2N1bV9hdHRzX2RmIDwtIHJlYWRfY3N2KCIuLi9vcmRlci1ib29rLXBsb3QtZmluZC9jdW1fZXJyb3JzL3Jlc291cmNlcy9mb3Jfd2ViX2FwcC9MS09ILTIwMDctMTAtMDhfb2JwX2N1bV9hdHRzLmNzdiIpDQojIG9icF9jdW1fYXR0c19kZiA8LSByZWFkX2NzdigiLi4vb3JkZXItYm9vay1wbG90LWZpbmQvY3VtX2Vycm9ycy9yZXNvdXJjZXMvZm9yX3dlYl9hcHAvczFfczJfMjAwN19vYnBfY3VtX2F0dHMuY3N2IikNCm9icF9jdW1fYXR0c19kZg0KYGBgDQoNCmBgYHtyfQ0Kb3JkZXJfYXR0c19jdW1zdW1zX2VuaGFuY2VkX2RmIDwtIGxlZnRfam9pbihvcmRlcl9hdHRzX2N1bXN1bXNfZGYsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnBzX2RmICU+JSBzZWxlY3QoLU9CUExPVE5PLCAtU0VDQ09ERSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGMoIk5PIiwgIkRBVEUiKSkgJT4lIA0KICBzZWxlY3QoTk8sIFNFQ0NPREUsIERBVEVUSU1FTUxMUywgUFJJQ0UsIFRSQURFUFJJQ0UsIFZPTFVNRSwgDQogICAgICAgICBEQVRFLCBUSU1FX1MsIE9CUExPVE5PLCBBVFQsIFZBTCwgDQogICAgICAgICBTSEFSRUJBTCwgQlBST0ZJVCwgU1BST0ZJVCwgT0JQTUlOVFBSSUNFLCBPQlBNQVhUUFJJQ0UsDQogICAgICAgICBDQk9WT0x0ZGNzLCBDU09WT0x0ZGNzLCBCT1ZPTHRkY3MsIFNPVk9MdGRjcywgQlRWT0x0ZGNzLCBTVFZPTHRkY3MsIA0KICAgICAgICAgQ0JPVk9Mb2JwY3MsIENTT1ZPTG9icGNzLCBCT1ZPTG9icGNzLCBTT1ZPTG9icGNzLCBCVFZPTG9icGNzLCBTVFZPTG9icGNzLA0KICAgICAgICAgc29icCwgYm9icCwgbWF4X3NvYnBfYm9icCwgbWludXNfbWF4X3NvYnBfYm9icCwgc3RkYXksIGJ0ZGF5LCBtYXhfc3RkX2J0ZCwNCiAgICAgICAgIG1pbnVzX21heF9zdGRfYnRkKQ0Kb3JkZXJfYXR0c19jdW1zdW1zX2VuaGFuY2VkX2RmDQpgYGANCg0KYGBge3J9DQpvYnBfbWlubWF4X2F0dHNfZGYgPC0gb3JkZXJfYXR0c19jdW1zdW1zX2VuaGFuY2VkX2RmICU+JSANCiAgc2VsZWN0KE5PLCBTRUNDT0RFLCBEQVRFLCBPQlBMT1ROTywgQVRULA0KICAgICAgICAgREFURVRJTUVNTExTLCBQUklDRSwgVFJBREVQUklDRSkgJT4lIA0KICBncm91cF9ieShTRUNDT0RFLCBEQVRFLCBPQlBMT1ROTykgJT4lIA0KICBzdW1tYXJpc2UoT0JQQkVHSU4gPSBtaW4oREFURVRJTUVNTExTKSwgT0JQRU5EID0gbWF4KERBVEVUSU1FTUxMUyksIA0KICAgICAgICAgICAgT0JQQkVHSU5OTyA9IG1pbihOTyksIE9CUEVORE5PID0gbWF4KE5PKSwNCiAgICAgICAgICAgIE9CUE1JTlBSSUNFID0gbWluKFBSSUNFKSwgT0JQTUFYUFJJQ0UgPSBtYXgoUFJJQ0UpKQ0Kb2JwX21pbm1heF9hdHRzX2RmDQpgYGANCg0KYGBge3J9DQpvYnBfY3VtX21pbm1heF9hdHRzX2RmIDwtIGxlZnRfam9pbihvYnBfY3VtX2F0dHNfZGYsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JwX21pbm1heF9hdHRzX2RmICU+JSBzZWxlY3QoU0VDQ09ERSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERBVEUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPQlBMT1ROTywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9CUEJFR0lOLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT0JQQkVHSU5OTywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9CUEVORE5PLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT0JQRU5ELA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT0JQTUlOUFJJQ0UsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPQlBNQVhQUklDRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGMoIlNFQ0NPREUiLCAiREFURSIsICJPQlBMT1ROTyIpKSAlPiUgDQogIHNlbGVjdChTRUNDT0RFLCBEQVRFLCBPQlBMT1ROTywgVFJBREVWT0wsIEJVWVNFTExPQlAsDQogICAgICAgICBPQlBCRUdJTiwgT0JQRU5ELCBPQlBCRUdJTk5PLCBPQlBFTkROTywgT0JQTUlOUFJJQ0UsIE9CUE1BWFBSSUNFLA0KICAgICAgICAgVFJBREVTTk9UUkFERVMpICMsIEJVWVNFTExZSUVMRCwgT0JQVERWT0xSQVRJTywgTUlOTUFYUkFUSU8pDQpvYnBfY3VtX21pbm1heF9hdHRzX2RmDQpgYGANCg0KYGBge3J9DQpvYXNfYXR0X2JzdCA8LSBvcmRlcl9hdHRzX2N1bXN1bXNfZW5oYW5jZWRfZGYgJT4lIA0KICBzZWxlY3QoTk8sIFNFQ0NPREUsIERBVEUsIE9CUExPVE5PLCBBVFQsIFRSQURFUFJJQ0UpICU+JSANCiAgZmlsdGVyKEFUVCA9PSAiQlRWT0wiIHwgQVRUID09ICJTVFZPTCIpDQpvYXNfYXR0X2JzdA0KYGBgDQoNCmBgYHtyfQ0Kb2JwX21pbm1heF90cmFkZXByaWNlIDwtIGZ1bmN0aW9uKHNlY2NvZGUsIGRhdGUsIG9icGxvdG5vLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnBiZWdpbm5vLCBvYnBlbmRubywgdHJhZGVzbm90cmFkZXMsIG1pbm1heCkgew0KICAjIHByaW50KHBhc3RlKGxlbmd0aChzZWNjb2RlKSwNCiAgIyAgICAgICAgICAgICBsZW5ndGgoZGF0ZSksDQogICMgICAgICAgICAgICAgbGVuZ3RoKG9icGxvdG5vKSwNCiAgIyAgICAgICAgICAgICBsZW5ndGgob2JwYmVnaW5ubyksDQogICMgICAgICAgICAgICAgbGVuZ3RoKG9icGVuZG5vKSwNCiAgIyAgICAgICAgICAgICBsZW5ndGgobWlubWF4KSkpDQogICMgcHJpbnQocGFzdGUoc2VjY29kZSwgZGF0ZSwgb2JwbG90bm8sIG9icGJlZ2lubm8sIG9icGVuZG5vLCBtaW5tYXgpKQ0KICAjIHNlcShsZW5ndGgob2JwbG90bm8pKQ0KICBpZih0cmFkZXNub3RyYWRlcyA9PSAiWSIpIHsNCiAgICBpZiAobWlubWF4ID09ICJtaW4iKSB7DQogICAgICBtaW50IDwtIG1pbihvYXNfYXR0X2JzdCAlPiUNCiAgICAgICAgICAgICAgICAgICAgZmlsdGVyKFNFQ0NPREUgPT0gc2VjY29kZSAmIERBVEUgPT0gZGF0ZSAmIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOTyA+PSBvYnBiZWdpbm5vICYgTk8gPD0gb2JwZW5kbm8pICU+JSANCiAgICAgICAgICAgICAgICAgICAgLiRUUkFERVBSSUNFICU+JQ0KICAgICAgICAgICAgICAgICAgICBjdW1taW4oKSkNCiAgICAgICMgcHJpbnQobWludCkNCiAgICAgIG1pbnQNCiAgICB9IGVsc2UgaWYgKG1pbm1heCA9PSAibWF4Iikgew0KICAgICAgbWF4dCA8LSBtYXgob2FzX2F0dF9ic3QgJT4lDQogICAgICAgICAgICAgICAgICAgIGZpbHRlcihTRUNDT0RFID09IHNlY2NvZGUgJiBEQVRFID09IGRhdGUgJiANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTk8gPj0gb2JwYmVnaW5ubyAmIE5PIDw9IG9icGVuZG5vKSAlPiUgDQogICAgICAgICAgICAgICAgICAgIC4kVFJBREVQUklDRSAlPiUNCiAgICAgICAgICAgICAgICAgICAgY3VtbWF4KCkpDQogICAgICAjIHByaW50KG1heHQpDQogICAgICBtYXh0DQogICAgICANCiAgICB9IGVsc2Ugew0KICAgICAgcHJpbnQocGFzdGUwKCJtaW4gb3IgbWF4IG9ubHksIG5vdCAiLCBtaW5tYXgpKQ0KICAgICAgc3RvcCgpDQogICAgfQ0KICB9IGVsc2Ugew0KICAgIE5BDQogIH0NCn0NCmBgYA0KDQpgYGB7cn0NCnZleHRvcl90b19vYnBfbWlubWF4X3RyYWRlcHJpY2UgPC0gZnVuY3Rpb24oc2VjY29kZSwgZGF0ZSwgb2JwbG90bm8sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnBiZWdpbm5vLCBvYnBlbmRubywgdHJhZGVzbm90cmFkZXMsIG1pbm1heCkgew0KICB0aWJibGUoc2VjY29kZSwgZGF0ZSwgb2JwbG90bm8sIG9icGJlZ2lubm8sIG9icGVuZG5vLCB0cmFkZXNub3RyYWRlcywNCiAgICAgICAgIG1pbm1heCA9IHJlcChtaW5tYXgsIGxlbmd0aChvYnBsb3RubykpKSAlPiUgDQogICAgcG1hcChvYnBfbWlubWF4X3RyYWRlcHJpY2UpICU+JSANCiAgICB1bmxpc3QoKQ0KfQ0KYGBgDQoNCmBgYHtyfQ0Kb2JwX2N1bV90cHJpY2VfYXR0cyA8LSBvYnBfY3VtX21pbm1heF9hdHRzX2RmICU+JSANCiAgIyBzYW1wbGVfbigyMCkgJT4lIA0KICBncm91cF9ieShTRUNDT0RFLCBEQVRFKSAlPiUgDQogIHN1bW1hcmlzZShPQlBMT1ROTyA9IE9CUExPVE5PLA0KICAgICAgICAgICAgT0JQTUlOVFJBREVQUklDRSA9IHZleHRvcl90b19vYnBfbWlubWF4X3RyYWRlcHJpY2UoU0VDQ09ERSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERBVEUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPQlBMT1ROTywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9CUEJFR0lOTk8sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPQlBFTkROTywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSQURFU05PVFJBREVTLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1pbiIpLA0KICAgICAgICAgICAgT0JQTUFYVFJBREVQUklDRSA9IHZleHRvcl90b19vYnBfbWlubWF4X3RyYWRlcHJpY2UoU0VDQ09ERSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERBVEUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPQlBMT1ROTywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9CUEJFR0lOTk8sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPQlBFTkROTywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSQURFU05PVFJBREVTLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1heCIpKQ0Kb2JwX2N1bV90cHJpY2VfYXR0cw0KYGBgDQoNCmBgYHtyfQ0Kb2JwX2N1bV9taW5tYXhfdHBtaW5tYXhfYXR0c19kZiA8LSBsZWZ0X2pvaW4ob2JwX2N1bV9taW5tYXhfYXR0c19kZiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9icF9jdW1fdHByaWNlX2F0dHMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGMoIlNFQ0NPREUiLCAiREFURSIsICJPQlBMT1ROTyIpKQ0Kb2JwX2N1bV9taW5tYXhfdHBtaW5tYXhfYXR0c19kZg0KYGBgDQoNCmBgYHtyfQ0Kb2JwX2N1bV9hdHRzX2VuaF9kZiA8LSBpbm5lcl9qb2luKG9icF9jdW1fbWlubWF4X3RwbWlubWF4X2F0dHNfZGYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJfYXR0c19jdW1zdW1zX2VuaGFuY2VkX2RmICU+JSBzZWxlY3QoU0VDQ09ERSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEQVRFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9CUExPVE5PLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJQUk9GSVQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU1BST0ZJVCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBjKCJTRUNDT0RFIiwgIkRBVEUiLCAiT0JQTE9UTk8iKSkgJT4lIA0KICBzZWxlY3QoU0VDQ09ERSwgREFURSwgT0JQTE9UTk8sIFRSQURFVk9MLCBCVVlTRUxMT0JQLA0KICAgICAgICAgQlBST0ZJVCwgU1BST0ZJVCwNCiAgICAgICAgIE9CUEJFR0lOLCBPQlBFTkQsIE9CUEJFR0lOTk8sIE9CUEVORE5PLCBPQlBNSU5QUklDRSwgT0JQTUFYUFJJQ0UsDQogICAgICAgICBPQlBNSU5UUkFERVBSSUNFLCBPQlBNQVhUUkFERVBSSUNFLCBUUkFERVNOT1RSQURFUykgJT4lICMsIEJVWVNFTExZSUVMRCwgT0JQVERWT0xSQVRJTywgTUlOTUFYUkFUSU8pICU+JSANCiAgcmVuYW1lKCJzZWNjb2RlIiA9ICJTRUNDT0RFIiwNCiAgICAgICAgICJkZGF0ZSIgPSAiREFURSIsDQogICAgICAgICAib2JwbG90bm8iID0gIk9CUExPVE5PIiwNCiAgICAgICAgICJ0cmFkZXZvbCIgPSAiVFJBREVWT0wiLA0KICAgICAgICAgImJ1eXNlbGxvYnAiID0gIkJVWVNFTExPQlAiLA0KICAgICAgICAgImJwcm9maXQiID0gIkJQUk9GSVQiLA0KICAgICAgICAgInNwcm9maXQiID0gIlNQUk9GSVQiLA0KICAgICAgICAgIm9icGJlZ2luIiA9ICJPQlBCRUdJTiIsDQogICAgICAgICAib2JwZW5kIiA9ICJPQlBFTkQiLA0KICAgICAgICAgIm9icGJlZ2lubm8iID0gIk9CUEJFR0lOTk8iLA0KICAgICAgICAgIm9icGVuZG5vIiA9ICJPQlBFTkROTyIsDQogICAgICAgICAib2JwbWlucHJpY2UiID0gIk9CUE1JTlBSSUNFIiwNCiAgICAgICAgICJvYnBtYXhwcmljZSIgPSAiT0JQTUFYUFJJQ0UiLA0KICAgICAgICAgIm9icG1pbnRyYWRlcHJpY2UiID0gIk9CUE1JTlRSQURFUFJJQ0UiLA0KICAgICAgICAgIm9icG1heHRyYWRlcHJpY2UiID0gIk9CUE1BWFRSQURFUFJJQ0UiLA0KICAgICAgICAgImJwcm9maXQiID0gIkJQUk9GSVQiLA0KICAgICAgICAgInNwcm9maXQiID0gIlNQUk9GSVQiLA0KICAgICAgICAgInRyYWRlc25vdHJhZGVzIiA9ICJUUkFERVNOT1RSQURFUyIpICU+JSANCiAgZGlzdGluY3QoKQ0Kb2JwX2N1bV9hdHRzX2VuaF9kZg0KYGBgDQoNCmBgYHtyfQ0KdGRfdm9sX3N1bV9kZiA8LSBvYnBfY3VtX2F0dHNfZW5oX2RmICU+JSANCiAgZ3JvdXBfYnkoc2VjY29kZSwgZGRhdGUpICU+JSANCiAgc3VtbWFyaXNlKHRkdm9sc3VtID0gc3VtKHRyYWRldm9sKSkNCg0Kb2JwX2N1bV9hdHRzX2VuaF92b2xhcnJhbmdlZF9kZiA8LSBsZWZ0X2pvaW4ob2JwX2N1bV9hdHRzX2VuaF9kZiwNCiAgICAgICAgICB0ZF92b2xfc3VtX2RmLA0KICAgICAgICAgIGJ5ID0gYygic2VjY29kZSIsICJkZGF0ZSIpKSAlPiUgDQogIG11dGF0ZShvYnBzaGFyZWludGQgPSB0cmFkZXZvbCAvIHRkdm9sc3VtKSAlPiUgDQogIHNlbGVjdCgtdGR2b2xzdW0pICU+JSANCiAgYXJyYW5nZShzZWNjb2RlLCBkZGF0ZSwgZGVzYyhvYnBzaGFyZWludGQpKQ0KDQpvYnBfY3VtX2F0dHNfZW5oX3ZvbGFycmFuZ2VkX2RmDQpgYGANCg0KYGBge3J9DQpvcHRpb25zKGRpZ2l0cy5zZWNzID0gMykNCm9icF9jdW1fYXR0c19lbmhfdm9sYXJyYW5nZWRfZGYgJT4lDQogIHdyaXRlX2NzdigiLi4vb3JkZXItYm9vay1wbG90LWZpbmQvY3VtX2Vycm9ycy9yZXNvdXJjZXMvZm9yX3dlYl9hcHAvb2JwX2N1bV9hdHRzX2VuaF9kZi5jc3YiLA0KICAgICAgICAgICAgbmEgPSAiIikNCmBgYA0KDQpgYGB7cn0NCm9yZGVyX2F0dHNfY3Vtc3Vtc19lbmgyX2RmIDwtIG9yZGVyX2F0dHNfY3Vtc3Vtc19lbmhhbmNlZF9kZiAlPiUgDQogIG11dGF0ZShwY29sb3IgPSBpZl9lbHNlKEFUVCA9PSAiQk9WT0wiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgImFxdWFtYXJpbmUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShBVFQgPT0gIlNPVk9MIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiY29yYWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIjMDA0NDgxIikpLA0KICAgICAgICAgcHNoYXBlID0gNEwsDQogICAgICAgICBwc2l6ZSA9IDAuNSkNCm9yZGVyX2F0dHNfY3Vtc3Vtc19lbmgyX2RmDQpgYGANCg0KYGBge3J9DQpvcmRlcl9hdHRzX2N1bXN1bXNfZW5oNF9kZiA8LSBvcmRlcl9hdHRzX2N1bXN1bXNfZW5oMl9kZiAlPiUgDQogIGFycmFuZ2UoU0VDQ09ERSwgREFURSwgTk8pICU+JSANCiAgcmVuYW1lKCJubm8iID0gIk5PIiwNCiAgICAgICAgICJzZWNjb2RlIiA9ICJTRUNDT0RFIiwNCiAgICAgICAgICJkYXRldGltZW1sbHMiID0gIkRBVEVUSU1FTUxMUyIsDQogICAgICAgICAicHJpY2UiID0gIlBSSUNFIiwNCiAgICAgICAgICJ0cmFkZXByaWNlIiA9ICJUUkFERVBSSUNFIiwNCiAgICAgICAgICJ2b2x1bWUiID0gIlZPTFVNRSIsDQogICAgICAgICAiZGRhdGUiID0gIkRBVEUiLA0KICAgICAgICAgInR0aW1lX3MiID0gIlRJTUVfUyIsDQogICAgICAgICAib2JwbG90bm8iID0gIk9CUExPVE5PIiwNCiAgICAgICAgICJhdHQiID0gIkFUVCIsDQogICAgICAgICAidmFsIiA9ICJWQUwiLA0KICAgICAgICAgInNoYXJlYmFsIiA9ICJTSEFSRUJBTCIpICU+JSANCiAgc2VsZWN0KC1CUFJPRklULCAtU1BST0ZJVCwgLU9CUE1JTlRQUklDRSwgLU9CUE1BWFRQUklDRSkNCiMgb3B0aW9ucyhkaWdpdHMuc2VjcyA9IDMpDQpvcmRlcl9hdHRzX2N1bXN1bXNfZW5oNF9kZiAlPiUNCiAgd3JpdGVfY3N2KCIuLi9vcmRlci1ib29rLXBsb3QtZmluZC9jdW1fZXJyb3JzL3Jlc291cmNlcy9mb3Jfd2ViX2FwcC9vcmRlcl9hdHRzX2N1bXN1bXNfZW5oNF9kZi5jc3YiLA0KICAgICAgICAgICAgbmEgPSAiIikNCm9yZGVyX2F0dHNfY3Vtc3Vtc19lbmg0X2RmDQpgYGANCg0KYGBge3J9DQpvcmRlcl9hdHRzX2N1bXN1bXNfZW5oNF9kZiAlPiUgDQogIGZpbHRlcihvYnBsb3RubyA9PSA0ODg1MSwgYXR0ID09ICJTVFZPTCIpICU+JSANCiAgc2VsZWN0KG5ubywgcHJpY2UsIGF0dCwgdHJhZGVwcmljZSwgc29icCwgYm9icCkNCmBgYA0KDQo=